/**
 * 模板渲染服务
 * 使用 Handlebars 渲染代码模板
 */

import type { DataTable, TableField } from "../types"
import type { CodeGenerationConfig } from "../templates/backend-frameworks"

// 模拟 Handlebars 的基本功能
interface TemplateData {
  [key: string]: any
}

/**
 * 模板渲染器
 */
export class TemplateRenderer {
  private config: CodeGenerationConfig
  private helpers: Map<string, Function>

  constructor(config: CodeGenerationConfig) {
    this.config = config
    this.helpers = new Map()
    this.registerHelpers()
  }

  /**
   * 注册 Handlebars 辅助函数
   */
  private registerHelpers(): void {
    // 转换为小驼峰命名
    this.helpers.set('lowerCase', (str: string) => {
      return str.charAt(0).toLowerCase() + str.slice(1)
    })

    // 转换为大驼峰命名
    this.helpers.set('upperFirst', (str: string) => {
      return str.charAt(0).toUpperCase() + str.slice(1)
    })

    // 转换为下划线命名
    this.helpers.set('underScore', (str: string) => {
      return str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '')
    })

    // 条件判断
    this.helpers.set('eq', (a: any, b: any) => a === b)
    this.helpers.set('ne', (a: any, b: any) => a !== b)
    this.helpers.set('gt', (a: any, b: any) => a > b)
    this.helpers.set('lt', (a: any, b: any) => a < b)

    // 逻辑运算
    this.helpers.set('and', (a: any, b: any) => a && b)
    this.helpers.set('or', (a: any, b: any) => a || b)
    this.helpers.set('not', (a: any) => !a)
  }

  /**
   * 渲染模板
   */
  render(template: string, data: TemplateData): string {
    let result = template

    // 替换变量
    result = this.replaceVariables(result, data)

    // 处理条件语句
    result = this.processConditionals(result, data)

    // 处理循环语句
    result = this.processLoops(result, data)

    return result
  }

  /**
   * 替换模板变量
   */
  private replaceVariables(template: string, data: TemplateData): string {
    return template.replace(/\{\{([^}]+)\}\}/g, (match, expression) => {
      const trimmed = expression.trim()
      
      // 处理辅助函数调用
      if (trimmed.includes(' ')) {
        return this.processHelper(trimmed, data)
      }
      
      // 处理简单变量
      return this.getValue(trimmed, data) || ''
    })
  }

  /**
   * 处理辅助函数
   */
  private processHelper(expression: string, data: TemplateData): string {
    const parts = expression.split(' ')
    const helperName = parts[0]
    const args = parts.slice(1)

    if (helperName.startsWith('#')) {
      // 块级辅助函数，在其他地方处理
      return `{{${expression}}}`
    }

    const helper = this.helpers.get(helperName)
    if (helper) {
      const resolvedArgs = args.map(arg => this.getValue(arg, data))
      return helper(...resolvedArgs)
    }

    return ''
  }

  /**
   * 处理条件语句
   */
  private processConditionals(template: string, data: TemplateData): string {
    // 处理 {{#if condition}} ... {{/if}}
    return template.replace(/\{\{#if\s+([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (match, condition, content) => {
      const conditionValue = this.evaluateCondition(condition.trim(), data)
      return conditionValue ? content : ''
    })
  }

  /**
   * 处理循环语句
   */
  private processLoops(template: string, data: TemplateData): string {
    // 处理 {{#each array}} ... {{/each}}
    return template.replace(/\{\{#each\s+([^}]+)\}\}([\s\S]*?)\{\{\/each\}\}/g, (match, arrayName, content) => {
      const array = this.getValue(arrayName.trim(), data)
      if (!Array.isArray(array)) return ''

      return array.map((item, index) => {
        const itemData = {
          ...data,
          ...item,
          '@index': index,
          '@first': index === 0,
          '@last': index === array.length - 1
        }
        return this.render(content, itemData)
      }).join('')
    })
  }

  /**
   * 评估条件表达式
   */
  private evaluateCondition(condition: string, data: TemplateData): boolean {
    // 处理简单条件
    if (!condition.includes(' ')) {
      const value = this.getValue(condition, data)
      return !!value
    }

    // 处理复杂条件 (如 eq, ne 等)
    const parts = condition.split(' ')
    if (parts.length >= 3) {
      const operator = parts[0]
      const left = this.getValue(parts[1], data)
      const right = this.getValue(parts[2], data)

      const helper = this.helpers.get(operator)
      if (helper) {
        return helper(left, right)
      }
    }

    return false
  }

  /**
   * 获取数据值
   */
  private getValue(path: string, data: TemplateData): any {
    // 处理字符串字面量
    if (path.startsWith('"') && path.endsWith('"')) {
      return path.slice(1, -1)
    }

    // 处理数字字面量
    if (/^\d+$/.test(path)) {
      return parseInt(path)
    }

    // 处理布尔字面量
    if (path === 'true') return true
    if (path === 'false') return false

    // 处理对象路径
    const keys = path.split('.')
    let value = data
    for (const key of keys) {
      if (value && typeof value === 'object') {
        value = value[key]
      } else {
        return undefined
      }
    }
    return value
  }

  /**
   * 为表生成模板数据
   */
  generateTableData(table: DataTable): TemplateData {
    const entityName = this.toPascalCase(table.name)
    const tableName = table.name
    const tableComment = table.comment || table.name

    // 处理字段
    const fields = table.fields.map(field => this.processField(field))
    const primaryKey = fields.find(f => f.isPrimaryKey)
    const queryFields = fields.filter(f => f.queryType && f.queryType !== 'none')
    const requiredFields = fields.filter(f => f.required && !f.isPrimaryKey)

    // 生成导入类型
    const importTypes = this.generateImportTypes(fields)

    return {
      // 基础信息
      basePackage: this.config.basePackage,
      entityName,
      tableName,
      tableComment,
      author: this.config.author,
      version: this.config.version,
      createTime: new Date().toISOString().split('T')[0],

      // 字段信息
      fields,
      primaryKey,
      queryFields,
      requiredFields,
      importTypes,

      // 关联信息
      hasRelations: false, // 暂时不支持关联
      relations: [],

      // 自定义查询
      hasCustomQueries: false,
      customQueries: []
    }
  }

  /**
   * 处理字段信息
   */
  private processField(field: TableField): any {
    return {
      fieldName: this.toCamelCase(field.name),
      columnName: field.name,
      javaType: this.mapToJavaType(field.type),
      comment: field.comment || field.name,
      isPrimaryKey: field.isPrimaryKey || false,
      required: field.required || false,
      isLogicDelete: field.name === 'deleted',
      queryType: field.queryType || 'eq',
      maxLength: field.maxLength,
      min: field.min,
      max: field.max,
      pattern: field.pattern,
      example: field.example
    }
  }

  /**
   * 生成导入类型
   */
  private generateImportTypes(fields: any[]): string[] {
    const types = new Set<string>()
    
    fields.forEach(field => {
      switch (field.javaType) {
        case 'LocalDateTime':
          types.add('java.time.LocalDateTime')
          break
        case 'LocalDate':
          types.add('java.time.LocalDate')
          break
        case 'BigDecimal':
          types.add('java.math.BigDecimal')
          break
      }
    })

    return Array.from(types)
  }

  /**
   * 映射数据库类型到Java类型
   */
  private mapToJavaType(dbType: string): string {
    const typeMap: Record<string, string> = {
      'varchar': 'String',
      'char': 'String',
      'text': 'String',
      'longtext': 'String',
      'int': 'Integer',
      'bigint': 'Long',
      'tinyint': 'Integer',
      'smallint': 'Integer',
      'decimal': 'BigDecimal',
      'double': 'Double',
      'float': 'Float',
      'datetime': 'LocalDateTime',
      'timestamp': 'LocalDateTime',
      'date': 'LocalDate',
      'time': 'LocalTime',
      'boolean': 'Boolean',
      'bit': 'Boolean'
    }

    const normalizedType = dbType.toLowerCase().split('(')[0]
    return typeMap[normalizedType] || 'String'
  }

  /**
   * 转换为PascalCase
   */
  private toPascalCase(str: string): string {
    return str.replace(/(^|_)([a-z])/g, (_, __, letter) => letter.toUpperCase())
  }

  /**
   * 转换为camelCase
   */
  private toCamelCase(str: string): string {
    const pascal = this.toPascalCase(str)
    return pascal.charAt(0).toLowerCase() + pascal.slice(1)
  }
}
